package com.egao.common.module.company.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.common.component.elasticsearch.entity.ElasticSearchConstants;
import com.egao.common.component.elasticsearch.service.ElasticSearchService;
import com.egao.common.core.exception.BusinessException;
import com.egao.common.core.exception.ParameterException;
import com.egao.common.core.utils.ExcelUtils;
import com.egao.common.core.web.JsonResult;
import com.egao.common.core.web.PageParam;
import com.egao.common.module.company.constants.AttachmentConstants;
import com.egao.common.module.company.constants.CheckRecordConstants;
import com.egao.common.module.company.constants.CompanyConstants;
import com.egao.common.module.company.constants.PreachConstants;
import com.egao.common.module.company.entity.*;
import com.egao.common.module.company.entity.vo.*;
import com.egao.common.module.company.mapper.FieldMapper;
import com.egao.common.module.company.mapper.PreachMapper;
import com.egao.common.module.company.service.*;
import com.egao.common.module.company.utils.CompanyUtil;
import com.egao.common.module.push.service.PositionMatchingService;
import com.egao.common.module.push.service.PushMsgService;
import com.egao.common.module.pushInformation.service.PushInformationService;
import com.egao.common.module.student.service.impl.StudentServiceImpl;
import com.egao.common.module.system.constants.EmailConstants;
import com.egao.common.module.system.entity.User;
import com.egao.common.module.system.service.EmailService;
import com.egao.common.module.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.concurrent.ExecutorService;

/**
 * 宣讲会(Preach)表服务实现类
 *
 * @author dl
 */
@Service
@Slf4j
public class PreachServiceImpl extends ServiceImpl<PreachMapper, Preach> implements PreachService {

    @Autowired
    private PositionService positionService;
    @Autowired
    private CompanyCheckRecordService companyCheckRecordService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private FieldRecordService fieldRecordService;
    @Autowired
    private FieldMapper fieldMapper;
    @Autowired
    private ElasticSearchService elasticSearchService;
    @Resource(name = "taskRunnerExecutor")
    private ExecutorService asyncExecutorService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private UserService userService;
    @Autowired
    private PreachWorkerService preachWorkerService;
    @Autowired
    private PreachLogService preachLogService;
    @Resource
    private PushInformationService pushInformationService;

    private final Logger logger = LoggerFactory.getLogger(PreachServiceImpl.class.getName());

    @Override
    @Transactional(readOnly = true)
    public List<PreachListVO> listPage(PageParam<PreachListVO> page) {
        // 申请时间
        page = (PageParam<PreachListVO>) CompanyUtil.putApplyTime(page);
        if (page.getPageData().get(PreachConstants.APPLY_TIME) != null) {
            String[] arr = page.getPageData().get(PreachConstants.APPLY_TIME).toString().split("~");
            if (arr.length > 0) {
                page.put("selectTimeStart", arr[0] + " 00:00:00");
            }
            if (arr.length > 1) {
                page.put("selectTimeEnd", arr[1] + " 23:59:59");
            }
        }
        Map<String, Object> map = page.getPageData();
        // 单位查询
        if (map.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) map.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            page.put("companyId", company.getId());
        }
        // 查询类型 岗位
        if (map.get(CompanyConstants.JOBS) != null) {
            String jobs = (String) map.get(CompanyConstants.JOBS);
            page.put("jobNameList", jobs.split("，"));
        }
        if (map.get(CompanyConstants.EDUCATION) != null) {
            String education = (String) map.get(CompanyConstants.EDUCATION);
            page.put("educationList", education.split("，"));
        }
        if (map.get(CompanyConstants.JOB_CATEGORY) != null) {
            String jobCategory = (String) map.get(CompanyConstants.JOB_CATEGORY);
            page.put("jobCategoryList", jobCategory.split("，"));
        }
        if (map.get(CompanyConstants.MAJORS) != null) {
            String majors = (String) map.get(CompanyConstants.MAJORS);
            page.put("majorsList", majors.split("，"));
        }
        return baseMapper.listPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult savePreach(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        Company company = positionService.getCompanyByUserId(preachFormVO.getCreateBy());
        if (company == null) {
            throw new BusinessException("单位不存在");
        }
        preachFormVO.setCompanyId(company.getId());
        preachFormVO.setCompanyName(company.getName());

        // 复制宣讲会vo到实体
        Preach preach = new Preach();
        BeanUtil.copyProperties(preachFormVO, preach);

        // 数据状态为未取消
        preach.setInvalid(CompanyConstants.VALID);

        // 保存宣讲会
        if (!save(preach)) {
            return JsonResult.error("保存失败");
        }

        // 保存附件
        attachmentService.saveAttach(preachFormVO.getAttachments(), preach.getId(), AttachmentConstants.TYPE_PREACH);

        // 保存来校宣讲人员信息
        List<PreachWorker> preachWorkerList = preachFormVO.getPreachWorkerList();
        preachWorkerList.forEach(d -> d.setPreachId(preach.getId()));
        preachWorkerService.saveBatch(preachWorkerList);

        // 保存推荐信息
        pushInformationService.save(preach.getCompanyId(), 2, preach.getId(), preach.getTitle());

        return JsonResult.ok("保存成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult updatePreach(PreachFormVO preachFormVO) {
        Preach old = baseMapper.selectById(preachFormVO.getId());
        if (old == null) {
            return JsonResult.error("没有查询到宣讲会信息");
        }
        String oldState = old.getState();
        Date oldHoldTime = old.getHoldTime();
        Integer oldHoldTimeType = old.getHoldTimeOneType();
        Integer oldField = old.getFieldId();

        Preach preach = getPreachByFormVO(preachFormVO);
        BeanUtil.copyProperties(preachFormVO, preach);

        // 审核状态为待审核
        preach.setState(CompanyConstants.RECRUIT_STATE_DSH);
        if (updateById(preach)) {
            // 清空举办场地信息
            baseMapper.updateField(preach.getId());

            // 修改前是审核通过状态就记录之前的数据
            if ("1".equals(oldState)) {
                PreachLog log = new PreachLog();
                log.setPreachId(preach.getId());
                log.setHoldTime(oldHoldTime);
                log.setHoldTimeType(oldHoldTimeType);
                Field field = fieldMapper.selectById(oldField);
                log.setFieldName(field != null ? field.getName() : "");
                preachLogService.save(log);
            }

            // 删除预约场地信息
            fieldRecordService.remove(new QueryWrapper<FieldRecord>().eq("type", PreachConstants.fieldRecordType).eq("business_id", preach.getId()));

            // 保存附件
            attachmentService.deleteAttach(preach.getId(), AttachmentConstants.TYPE_PREACH);
            attachmentService.saveAttach(preachFormVO.getAttachments(), preach.getId(), AttachmentConstants.TYPE_PREACH);
            return JsonResult.ok("修改成功");
        }
        return JsonResult.error("修改失败");
    }

    @Override
    public JsonResult deletePreach(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        if (preachFormVO.getId() == null) {
            throw new ParameterException("宣讲会信息编号为空");
        }

        Preach preach = getById(preachFormVO.getId());
        if (preach == null) {
            throw new BusinessException("宣讲会信息为空");
        }

        if (removeById(preach)) {
            attachmentService.deleteAttach(preach.getId(), AttachmentConstants.TYPE_PREACH);
            fieldRecordService.remove(new QueryWrapper<FieldRecord>().eq("business_id", preach.getId()).eq("type", 1));
            String id = ElasticSearchConstants.INFORMATION_PREACH + "-" + preach.getId();
            elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @Override
    @Transactional(readOnly = true)
    public JsonResult detail(Integer id) {
        if (id == null) {
            throw new ParameterException("宣讲会信息编号为空");
        }

        Preach preach = getById(id);
        if (preach == null) {
            throw new BusinessException("宣讲会信息不存在");
        }

        PreachFormVO preachFormVO = new PreachFormVO();
        BeanUtil.copyProperties(preach, preachFormVO);

        // 单位发布需要查询职位
        if (preach.getPositionIds() != null) {
            List<Position> positions = positionService.getPositionByIds(preach.getPositionIds());
            if (positions != null && positions.size() > 0) {
                preachFormVO.setPositions(positions);
            }
        }

        // 查询发布的附件
        List<Attachment> attachments = attachmentService.getAttachByBusinessId(id, AttachmentConstants.TYPE_PREACH);
        if (attachments != null && attachments.size() > 0) {
            preachFormVO.setAttachments(attachments);
        }

        // 查询场地
        Field field = fieldMapper.selectById(preach.getFieldId());
        if (field != null) {
            preachFormVO.setFieldName(field.getName());
            preachFormVO.setFieldId(field.getId());
        }

        // 查询场地预约记录
        FieldRecord fieldRecord = fieldRecordService.getOne(new LambdaQueryWrapper<FieldRecord>().eq(FieldRecord::getBusinessId, id));
        FieldRecordVO fieldRecordVO = new FieldRecordVO();
        BeanUtil.copyProperties(fieldRecord, fieldRecordVO);
        preachFormVO.setFieldRecordVO(fieldRecordVO);

        // 查询单位修改记录
        List<PreachLog> preachLogList = preachLogService.list(new LambdaQueryWrapper<PreachLog>()
                .eq(PreachLog::getPreachId, preach.getId())
                .orderByDesc(PreachLog::getCreateTime)
        );
        preachFormVO.setPreachLogList(preachLogList);

        return JsonResult.ok("查询成功").setData(preachFormVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult checkPreach(PreachFormVO preachFormVO) {
        Preach preach = getPreachByFormVO(preachFormVO);
        BeanUtil.copyProperties(preachFormVO, preach);

        Date holdTime = getHoldTime(preachFormVO);
        preach.setHoldTime(holdTime);
        preach.setFieldId(preachFormVO.getFieldId());
        preach.setApplyTimeType(preachFormVO.getApplyTimeType());
        if (!updateById(preach)) {
            return JsonResult.error("保存失败");
        }

        // 审核通过保存场地预约记录
        if (CheckRecordConstants.CHECK_SUCCESS.equals(preachFormVO.getState())) {
            if (preachFormVO.getFieldRecordVO() == null) {
                throw new BusinessException("没有场地预约信息");
            }

            // 新场地需要删除旧纪录并且新增新记录
            if (preachFormVO.getFieldRecordVO().getId() == null) {
                // 检查场地时间是否冲突
                List<FieldRecord> fieldRecordList = fieldRecordService.list(new LambdaQueryWrapper<FieldRecord>()
                        .eq(FieldRecord::getStartDate, preachFormVO.getFieldRecordVO().getStartDate())
                        .eq(FieldRecord::getFieldId, preachFormVO.getFieldRecordVO().getFieldId())
                        .ne(FieldRecord::getBusinessId, preachFormVO.getId())
                );
                for (FieldRecord record : fieldRecordList) {
                    boolean b = record.getStartTime().before(preachFormVO.getFieldRecordVO().getEndTime()) && record.getEndTime().after(preachFormVO.getFieldRecordVO().getStartTime());
                    if (b) {
                        throw new BusinessException("场地预约时间冲突");
                    }
                }

                // 删除旧纪录保存新记录
                fieldRecordService.remove(new LambdaQueryWrapper<FieldRecord>().eq(FieldRecord::getBusinessId, preach.getId()));
                FieldRecord fieldRecord = new FieldRecord();
                BeanUtil.copyProperties(preachFormVO.getFieldRecordVO(), fieldRecord);
                fieldRecordService.save(fieldRecord);
            }
        } else {
            // 删除场地预约记录
            fieldRecordService.remove(new LambdaQueryWrapper<FieldRecord>().eq(FieldRecord::getBusinessId, preach.getId()));
        }

        asyncExecutorService.submit(() -> {
            // 需要发送邮件通知
            if (CompanyConstants.SUCCESS.equals(preach.getEmailFlag())) {
                //发送邮件
                Company company = companyService.getById(preach.getCompanyId());
                if (company != null) {
                    User user = userService.getById(company.getUserId());
                    if (user != null) {
                        String[] email = {user.getUsername()};
                        emailService.sendTextEmail(EmailConstants.TITLE_PREACH_CHECK, preach.getStateContent(), email);
                    }
                }
            }

            // 审核通过 更新推送信息
            if (CheckRecordConstants.CHECK_SUCCESS.equals(preach.getState())) {
                pushInformationService.checkPushState(2, preach.getId());
            }

            // 保存es
            if (CheckRecordConstants.CHECK_SUCCESS.equals(preach.getState())) {
                Field field = fieldMapper.selectById(preach.getFieldId());
                String id = ElasticSearchConstants.INFORMATION_PREACH + "-" + preach.getId();
                elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
                preach.setHoldAddress(field.getName());
                elasticSearchService.save(preach);
            }
        });
        return JsonResult.ok("审核成功");
    }

    @Override
    public JsonResult removePreach(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        if (preachFormVO.getId() == null) {
            throw new ParameterException("宣讲会信息编号为空");
        }

        Preach preach = getById(preachFormVO.getId());
        if (preach == null) {
            throw new BusinessException("宣讲会信息为空");
        }

        if (removeById(preach)) {
            attachmentService.deleteAttach(preach.getId(), AttachmentConstants.TYPE_PREACH);
            fieldRecordService.remove(new QueryWrapper<FieldRecord>().eq("business_id", preach.getId()).eq("type", 1));
            String id = ElasticSearchConstants.INFORMATION_PREACH + "-" + preach.getId();
            elasticSearchService.delete(ElasticSearchConstants.INDEX_NAME_INFORMATION, id);
            return JsonResult.ok("删除成功");
        }
        return JsonResult.error("删除失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult cancelPreach(PreachFormVO preachFormVO) {
        Preach preach = getPreachByFormVO(preachFormVO);

        //审核状态为待审核
        preach.setInvalid(PreachConstants.cancelType);
        if (updateById(preach)) {
            baseMapper.updateField(preach.getId());
            fieldRecordService.remove(new QueryWrapper<FieldRecord>().eq("type", PreachConstants.fieldRecordType).eq("business_id", preach.getId()));
            return JsonResult.ok("取消成功");
        }
        return JsonResult.error("取消失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult savePreachSchool(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        //复制宣讲会vo到实体
        Preach preach = new Preach();
        BeanUtil.copyProperties(preachFormVO, preach);
        // 学校发布默认为第一个申请时间
        preach.setApplyTimeType("1");
        preach.setHoldTimeOneType(preach.getChoiceHoldTimeType());
        preach.setHoldTimeOneHour(preach.getChoiceHoldTimeHour());
        preach.setHoldTimeOneDate(preach.getChoiceHoldTimeDate());
        Date holdTime = getHoldTime(preachFormVO);
        preach.setHoldTime(holdTime);
        preach.setAddType("2");

        //数据状态为未取消
        preach.setInvalid(CompanyConstants.VALID);

        if (save(preach)) {
            // 保存附件
            attachmentService.saveAttach(preachFormVO.getAttachments(), preach.getId(), AttachmentConstants.TYPE_PREACH);

            if (preachFormVO.getLockType() == 1) {
                FieldRecordFormVO fieldRecordFormVO = new FieldRecordFormVO();
                fieldRecordFormVO.setBusinessId(preach.getId());
                fieldRecordFormVO.setType(preachFormVO.getLockType());
                fieldRecordFormVO.setFieldId(preachFormVO.getFieldId());
                fieldRecordFormVO.setTitle(preach.getTitle());
                fieldRecordFormVO.setStartDate(preachFormVO.getLockStartDate());
                fieldRecordFormVO.setStartTime(preachFormVO.getLockStartTime());
                fieldRecordFormVO.setEndTime(preachFormVO.getLockEndTime());
                fieldRecordFormVO.setDataField(preachFormVO.getDataField());
                fieldRecordService.lockFieldRecord(fieldRecordFormVO);
            }

            // 保存场地
            // FieldRecord record = new FieldRecord();
            // record.setBusinessId(preach.getId());
            // record.setFieldId(preachFormVO.getFieldId());
            // record.setStartDate(preachFormVO.getChoiceHoldTimeDate());
            // record.setStartTime(preachFormVO.getChoiceHoldTimeDate());
            // record.setTimeType(String.valueOf(preachFormVO.getChoiceHoldTimeType()));
            // record.setType(PreachConstants.fieldRecordType);
            // fieldRecordService.save(record);


            return JsonResult.ok("提交成功");
        }


        return JsonResult.error("提交失败");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JsonResult updatePreachSchool(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        //复制宣讲会vo到实体
        Preach preach = new Preach();
        BeanUtil.copyProperties(preachFormVO, preach);
        preach.setHoldTimeOneType(preach.getChoiceHoldTimeType());
        preach.setHoldTimeOneHour(preach.getChoiceHoldTimeHour());
        preach.setHoldTimeOneDate(preach.getChoiceHoldTimeDate());
        Date holdTime = getHoldTime(preachFormVO);
        preach.setHoldTime(holdTime);

        if (updateById(preach)) {
            updatePreachField(preachFormVO, preach);

            return JsonResult.ok("提交成功");
        }
        return JsonResult.error("提交失败");
    }

    @Override
    public JsonResult countPreach(PageParam<PreachListVO> page) {
        //申请时间
        page = (PageParam<PreachListVO>) CompanyUtil.putHoldTime(page);
        page.getPageData().put("state", CompanyConstants.COMPANY_STATE_PASS);
        page.setSearchCount(false);
        page.setSize(100);
        Map<String, Object> map = new HashMap<>(5);
        Integer total = baseMapper.countTotal(page);
        List<Map<String, Object>> provinceList = baseMapper.countProvince(page);
        List<Map<String, Object>> natureList = baseMapper.countNature(page);
        List<Map<String, Object>> industryList = baseMapper.countIndustry(page);
        List<Map<String, Object>> scaleList = baseMapper.countScale(page);
        map.put("total", total);
        map.put("provinceList", provinceList);
        map.put("natureList", natureList);
        map.put("industryList", industryList);
        map.put("scaleList", scaleList);
        return JsonResult.ok().setData(map);
    }

    @Override
    public List<Preach> effectiveList(Date startDate, Date endDate) {
        return baseMapper.selectList(new LambdaQueryWrapper<Preach>()
                .eq(Preach::getInvalid, PreachConstants.INVALID)
                .eq(Preach::getState, PreachConstants.STATE_PASS)
                .ge(startDate != null, Preach::getHoldTime, startDate)
                .le(endDate != null, Preach::getHoldTime, endDate)
        );
    }

    private void updatePreachField(PreachFormVO preachFormVO, Preach preach) {
        attachmentService.deleteAttach(preach.getId(), AttachmentConstants.TYPE_PREACH);
        attachmentService.saveAttach(preachFormVO.getAttachments(), preach.getId(), AttachmentConstants.TYPE_PREACH);

        fieldRecordService.remove(new QueryWrapper<FieldRecord>().eq("type", PreachConstants.fieldRecordType).eq("business_id", preach.getId()));
        // 保存场地
        FieldRecord record = new FieldRecord();
        record.setBusinessId(preach.getId());
        record.setFieldId(preachFormVO.getFieldId());
        record.setStartDate(preachFormVO.getChoiceHoldTimeDate());
        record.setStartTime(preachFormVO.getChoiceHoldTimeDate());
        record.setTimeType(String.valueOf(preachFormVO.getChoiceHoldTimeType()));
        record.setType(PreachConstants.fieldRecordType);
        fieldRecordService.save(record);
        // 审核记录
        CompanyCheckRecord companyCheckRecord = new CompanyCheckRecord();
        companyCheckRecord.setCompanyId(preach.getCompanyId());
        companyCheckRecord.setState(preach.getState());
        companyCheckRecord.setStateContent(preach.getStateContent());
        companyCheckRecord.setCheckUserId(preachFormVO.getCheckUserId());
        companyCheckRecord.setType(CheckRecordConstants.CHECK_PREACH);
        companyCheckRecord.setBusinessId(preach.getId());
        companyCheckRecordService.save(companyCheckRecord);
    }


    /**
     * 验证宣讲会表单是否为空
     *
     * @param preachFormVO 宣讲会表单
     * @return
     */
    private void verifyPreach(PreachFormVO preachFormVO) {
        if (preachFormVO == null) {
            throw new ParameterException("宣讲会信息为空");
        }
    }

    /**
     * 获取需要修改宣讲会信息
     *
     * @param preachFormVO 宣讲会表单
     */
    private Preach getPreachByFormVO(PreachFormVO preachFormVO) {
        verifyPreach(preachFormVO);

        if (preachFormVO.getId() == null) {
            throw new ParameterException("宣讲会编号为空");
        }

        Preach preach = getById(preachFormVO.getId());
        if (preach == null) {
            throw new BusinessException("宣讲会信息为空");
        }

        return preach;
    }

    /**
     * 获取举办时间
     *
     * @param preachFormVO 宣讲会表单对象
     * @return Date 举办时间
     */
    private Date getHoldTime(PreachFormVO preachFormVO) {
        Date time = preachFormVO.getChoiceHoldTimeDate();
        String date = DateUtil.format(time, "yyyy-MM-dd");
        String holdTime = date + " " + preachFormVO.getChoiceHoldTimeHour() + ":00";
        if (Objects.isNull(preachFormVO.getChoiceHoldTimeHour())) {
            throw new BusinessException("未分配场地！");
        }
        return DateUtil.parse(holdTime, "yyyy-MM-dd HH:mm:ss");
    }

    @Override
    public void exportExcel(Map<String, Object> page, HttpServletResponse response) {
        Object pageDataObj = page.get("pageData");
        HashMap<String, Object> hashMap = null;
        if (pageDataObj instanceof HashMap) {
            hashMap = (HashMap<String, Object>) pageDataObj;
        } else {
            logger.error("pageData 不是 HashMap 类型");
            return;
        }

        try {
            processHashMap(hashMap);
        } catch (BusinessException e) {
            logger.error("处理查询条件时出错: " + e.getMessage(), e);
            return;
        }

        page.put("pageData", hashMap);

        List<PreachExcelVO> list = baseMapper.listExcel(page);

        String fileName = "preach-" + DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN) + ".xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);

        try (OutputStream out = response.getOutputStream();
             ExcelWriter writer = ExcelUtil.getWriter(true)) {
            // 在第一行之前添加标题、总记录数、企业个数
            List<Object> titleRow = new ArrayList<>();
            if (hashMap.get("selectTimeStart") != null && hashMap.get("selectTimeEnd") != null) {
                titleRow.add(hashMap.get("selectTimeStart").toString().split(" ")[0] + "~" + hashMap.get("selectTimeEnd").toString().split(" ")[0] + "校内宣讲会信息");
            } else if (hashMap.get("selectTimeStart") != null && hashMap.get("selectTimeEnd") == null) {
                titleRow.add(hashMap.get("selectTimeStart").toString().split(" ")[0] + "至今" + "校内宣讲会信息");
            } else if (hashMap.get("selectTimeStart") == null && hashMap.get("selectTimeEnd") != null) {
                titleRow.add("至" + hashMap.get("selectTimeEnd").toString().split(" ")[0] + "校内宣讲会信息");
            } else {
                titleRow.add("校内宣讲会信息");
            }
            writer.writeRow(titleRow);

            // 获取总记录数和企业个数
            int totalCount = list.size();
            int companyCount = companyCount(list);
            List<Object> totalRow = new ArrayList<>();
            totalRow.add("校内宣讲会总记录数: " + totalCount);
            totalRow.add("企业个数: " + companyCount);
            writer.writeRow(totalRow);

            excelAddHeaderAlias(writer);
            writer.write(list, true);

            // 设置列自适应宽 必须在 write 以后
            ExcelUtils.autoColumnMaxSizeAll(writer.getSheet());
            writer.flush(out, true);
        } catch (IOException e) {
            logger.error("导出失败 - PreachServiceImpl - exportExcel", e);
        }
    }

    /**
     * 为导出对象设置别名和排序 排序顺序为 add 顺序
     *
     * @param writer ExcelWriter
     */
    public void excelAddHeaderAlias(ExcelWriter writer) {
        writer.addHeaderAlias("title", "标题");
        writer.addHeaderAlias("companyName", "单位名称");
        writer.addHeaderAlias("holdTime", "举办时间");
        writer.addHeaderAlias("fieldName", "举办场地");
    }

    /**
     * 实现时间段查询包含 timeEnd 当天记录，同时实现多单位、多岗位类型查询
     *
     * @param hashMap
     */
    private void processHashMap(HashMap<String, Object> hashMap) {
        // 举办时间查询
        if (hashMap.get("selectTime") != null) {
            String[] arr = hashMap.get("selectTime").toString().split("~");
            if (arr.length > 0) {
                hashMap.put("selectTimeStart", arr[0] + " 00:00:00");
            }
            if (arr.length > 1) {
                hashMap.put("selectTimeEnd", arr[1] + " 23:59:59");
            }
        }

        // 发布时间查询
        if (hashMap.get("applyTime") != null) {
            String[] arr = hashMap.get("applyTime").toString().split("~");
            if (arr.length > 0) {
                hashMap.put("createTimeStart", arr[0] + " 00:00:00");
            }
            if (arr.length > 1) {
                hashMap.put("createTimeEnd", arr[1] + " 23:59:59");
            }
        }

        // 单位查询
        if (hashMap.get(CompanyConstants.USER) != null) {
            Integer userId = (Integer) hashMap.get(CompanyConstants.USER);
            Company company = positionService.getCompanyByUserId(userId);
            if (company == null) {
                throw new BusinessException("单位不存在");
            }
            hashMap.put("companyId", company.getId());
        }

        // 查询类型 岗位
        if (hashMap.get(CompanyConstants.JOBS) != null) {
            String jobs = (String) hashMap.get(CompanyConstants.JOBS);
            hashMap.put("jobNameList", jobs.split("，"));
        }
        if (hashMap.get(CompanyConstants.EDUCATION) != null) {
            String education = (String) hashMap.get(CompanyConstants.EDUCATION);
            hashMap.put("educationList", education.split("，"));
        }
        if (hashMap.get(CompanyConstants.JOB_CATEGORY) != null) {
            String jobCategory = (String) hashMap.get(CompanyConstants.JOB_CATEGORY);
            hashMap.put("jobCategoryList", jobCategory.split("，"));
        }
        if (hashMap.get(CompanyConstants.MAJORS) != null) {
            String majors = (String) hashMap.get(CompanyConstants.MAJORS);
            hashMap.put("majorsList", majors.split("，"));
        }
    }

    /**
     * 查询企业个数
     *
     * @param list
     */
    private int companyCount(List<PreachExcelVO> list) {
        Set<String> companyNameSet = new HashSet<>();
        for (PreachExcelVO vo : list) {
            String companyName = vo.getCompanyName();
            if (companyName != null) {
                companyNameSet.add(companyName);
            }
        }
        return companyNameSet.size();
    }

}